// Copyright 2011 Bryan McKelvey, MIT License

/**
 * @fileoverview An individual security quote and its associated methods
 * @author bryan.mckelvey@gmail.com (McKelvey Bryan)
 */

/**
 * This is the object which represents an individual security quote
 * @constructor
 * @param {string} secid The security ID
 * @param {string} source The pricing source (Bloomberg, Google, Yahoo!, Quote.com)
 * @param {number} count The number of shares owned
 * @param {number} pricePaid The price paid for each of the shares owned
 * @param {number} decimals The number of decimals to include in the price
 * @param {string} trigger The conditions for alerting the user
 * @param {boolean} isTotal Currently unused
 */
function Quote(secid, source, count, pricePaid, decimals, trigger, isTotal) {
  this.secid = secid;
  this.source = source;
  this.count = count;
  this.pricePaid = pricePaid;
  this.title = "";
  this.value = 0;
  this.change = 0;
  this.decimals = decimals;
  this.trigger = trigger;
  this.triggered = false;
  this.tr;
}

/**
 * Gets the value of the quote for a given metric
 * @param {Object} metric The metric to evaluate
 * @returns {number|string}
 */
Quote.prototype.get = function(metric) {
  return Metrics.calculate(metric, this);
};

/**
 * Loads tickers via a $.ajax call to the source URL and parsing the output
 * with a regular expression
 * @returns The current object
 * @type Quote
 */
Quote.prototype.loadTicker = function() {
  var regex = Sources.get(this.source).regex;
  var parentScope = this;

	$.ajax({
		type: 'get',
		url: Sources.get(this.source).url + this.secid,
		dataType: 'text',
		success: function(vals){
      var matches = regex.title.exec(vals);
      parentScope.title = matches[1];
      matches = regex.value.exec(vals);
      parentScope.value = parseFloat(matches[1].replace(",", ""));
      matches = regex.change.exec(vals);
      if (parentScope.source == "yahoo" &&
				  matches[0].indexOf("price-change-down") !== -1) {
        parentScope.change = -parseFloat(matches[1].replace(",", ""));
      } else {
        parentScope.change = parseFloat(matches[1].replace(",", ""));
      }
      
      // Set change to 0 if it's invalid
      if (isNaN(Number(parentScope.change))) {
        parentScope.change = 0;
      }

      parentScope.checkTrigger();			
		}
	});
	return this;
};

/**
 * Draws a row in the quote table
 * @returns The generated table row
 * @type Node
 */
Quote.prototype.drawRow = function() {
  var parentScope = this;
  var $tr = $('<tr>').click(function() { Sources.graph(parentScope.secid, parentScope.source); });
  for (var i = 0; i < Metrics.count(); i++) {
    var metric = Metrics.column(i);
    var data = parentScope.get(metric);
    $tr.append(parentScope.append(data, Metrics.get(metric).type));
  }
  this.tr = $tr[0];
  return $tr[0];
};

/**
 * Creates a table cell based on a supplied value and metric type  
 * @param {number|string} x The value to append
 * @param {string} metric A string representing the metric's type
 * @returns The table cell generated
 * @type Object
 */
Quote.prototype.append = function(x, metric) {
  var $td = $('<td>');
  var text;
  var color = true;

  switch (metric) {
    case "text":
      $td.addClass('text').text(x.replace("amp;", ""));
      break;
    case "value":
      color = false;
    case "change":
    case "pct":
      var num = Number(x);
      var decimals = (metric == "pct" ? (this.decimals > 1 ? this.decimals - 1 : 1) : this.decimals);
      $td.addClass('value');

      if (isNaN(num) || num === 0) {
        $td.text("―");
      } else if (num < 0) {
        $td.text(num.toFixed(decimals));
        if (color === true) {
          $td.addClass('valuedown');
        }
      } else {
        if (color === true) {
          $td.addClass('valueup').text('+' + num.toFixed(decimals));
        } else {
          $td.text(num.toFixed(decimals));
        }
      }
      break;
    default:
      break;
  }

  return $td;
};

/**
 * Checks whether a trigger condition has been met, and if so alerts the user
 * @returns The current object
 * @type Quote
 */
Quote.prototype.checkTrigger = function() {
  if (!this.triggered && this.trigger !== "") {
    var temp = this.trigger.split(",");
    for (var i = 0; i < temp.length; i++) {
      var operator = temp[i].substring(0, 1) +
				(temp[i].substring(1, 2) === "=" ? "=" : "");
      var limit = parseFloat(temp[i].replace(operator, ""));
      var pastLimit = false;
      var preposition = "";
      
      switch (temp[i].substring(0, 1) + (temp[i].substring(1, 2) === "=" ? "=" : "")) {
        case ">":
          preposition = "above";
          pastLimit = (this.value > limit);
          break;
        case ">=":
          preposition = "above";
          pastLimit = (this.value >= limit);
          break;
        case "<=":
          preposition = "below";
          pastLimit = (this.value <= limit);
          break;
        case "<":
          preposition = "below";
          pastLimit = (this.value < limit);
          break;
        default:
          break;
      }

      if (pastLimit) {
        var notification = webkitNotifications.createHTMLNotification(
          chrome.extension.getURL("notification.html?text=<b>" + this.secid +
            "</b> is currently trading at <b>" + this.value.toFixed(this.decimals) + "</b>, " +
            preposition + " your limit of <b>" + limit.toFixed(this.decimals) + "</b>.<br><br>" +
            "<a href=\"javascript:Notification.exit()\">Close</a> | " +
            "<a href=\"javascript:Notification.disarm('" + this.secid + "','" + temp[i] + "')\">Disable this alert</a>"));
        notification.show();
        this.triggered = true;
        break;
      }
    }
  }
	return this;
};